package com.sys.console.action;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Date;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.sys.console.business.SysModuleService;
import com.sys.console.business.SysUserService;
import com.sys.console.common.VerifyCodeUtil;
import com.sys.console.cookie.Constant_Cookie;
import com.sys.console.mapper.SysUserLoginLogsMapper;
import com.sys.console.monitor.LoginLogs;
import com.sys.console.pojo.Sys_User;
import com.sys.object.common.ObjResultCode;
import com.sys.object.common.ObjResultException;
import com.sys.object.common.utils.IpUtils;

@Controller
public class HomeAction {
	public final Logger sysLoger = Logger.getLogger("sysLoger");

	@Autowired
	SysUserService sysUserService;
	@Autowired
	SysModuleService sysModuleService;
	@Autowired
	SysUserLoginLogsMapper sysUserLoginLogsMapper;

	/**
	 * 系统登陆
	 * 
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/login.do", method = RequestMethod.GET)
	public String login(Model model) {
		return "/login";
	}

	/**
	 * 系统登陆
	 * 
	 * @param user
	 * @param bindingResult
	 * @param redirectAttributes
	 * @return
	 */
	@RequestMapping(value = "/login.do", method = RequestMethod.POST)
	public String login(Sys_User sysUser, RedirectAttributes redirectAttributes, HttpServletRequest request,
			Model model, HttpServletResponse response) {

		ObjResultException<String> ret = new ObjResultException<String>();
		try {
			if (!StringUtils.hasText(sysUser.getUsername()) && !StringUtils.hasText(sysUser.getPassword())) {
				ret.setResultCode(ObjResultCode.SYS_USER_NAME_PASS_NULL);
				model.addAttribute("ret", ret);
				return "/login";
			}

			if (!StringUtils.hasText(sysUser.getUsername())) {
				ret.setResultCode(ObjResultCode.USER_NAME_NULL);
				model.addAttribute("ret", ret);
				return "/login";
			}

			if (!StringUtils.hasText(sysUser.getPassword())) {
				ret.setResultCode(ObjResultCode.USER_PASS_NULL);
				model.addAttribute("ret", ret);
				return "/login";
			}
			UsernamePasswordToken token = new UsernamePasswordToken(sysUser.getUsername(), sysUser.getPassword());
			token.setRememberMe(true);
			// 获取当前的Subject
			Subject currentUser = SecurityUtils.getSubject();
			try {
				// 在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查
				// 每个Realm都能在必要时对提交的AuthenticationTokens作出反应
				// 所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法
				// System.out.println("对用户[" + sysUser.getUsername() +
				// "]进行登录验证..验证开始");
				currentUser.login(token);
				// System.out.println("对用户[" + sysUser.getUsername() +
				// "]进行登录验证..验证通过");

			} catch (UnknownAccountException uae) {
				System.out.println("对用户[" + sysUser.getUsername() + "]进行登录验证..验证未通过,未知账户");
				// request.setAttribute("message", "未知账户");
				ret.setResultCode(ObjResultCode.USER_LOGIN_DELETE);
				model.addAttribute("ret", ret);
				return "/login";
			} catch (IncorrectCredentialsException ice) {
				System.out.println("对用户[" + sysUser.getUsername() + "]进行登录验证..验证未通过,错误的凭证");
				// request.setAttribute("message", "密码不正确");
				ret.setResultCode(ObjResultCode.USER_PASSWORD_ERROR);
				model.addAttribute("ret", ret);
				return "/login";
			} catch (LockedAccountException lae) {
				System.out.println("对用户[" + sysUser.getUsername() + "]进行登录验证..验证未通过,账户已锁定");
				// request.setAttribute("message", "账户已锁定");
				ret.setResultCode(ObjResultCode.USER_ACCOUNT_LOCKED);
				model.addAttribute("ret", ret);
				return "/login";
			} catch (ExcessiveAttemptsException eae) {
				System.out.println("对用户[" + sysUser.getUsername() + "]进行登录验证..验证未通过,错误次数过多");
				// request.setAttribute("message", "用户名或密码错误次数过多");
				ret.setResultCode(ObjResultCode.USER_LOGIN_TIMES_ERROR);
				model.addAttribute("ret", ret);
				return "/login";

			} catch (AuthenticationException ae) {
				ae.printStackTrace();
				// 通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景
				System.out.println("对用户[" + sysUser.getUsername() + "]进行登录验证..验证未通过,堆栈轨迹如下");
				ae.printStackTrace();
				// request.setAttribute("message", "用户名或密码不正确");
				ret.setResultCode(ObjResultCode.USER_LOGIN_USERNAME_PASSWORD_ERROR);
				model.addAttribute("ret", ret);
				return "/login";
			}
			// 验证是否登录成功
			if (currentUser.isAuthenticated()) {
				System.out.println("用户[" + sysUser.getUsername() + "]登录认证通过(这里可以进行一些认证通过后的一些系统参数初始化操作)");
				// 更新登陆日志
				try {
					Sys_User User = (Sys_User) request.getSession().getAttribute(Constant_Cookie.CURRENT_USER_SESSION);
					User.setLtime(new Date());
					User.setLip(IpUtils.getIpAddr(request));
					sysUserService.updateLoginInfo(User);
					LoginLogs.monSaveLoginInfo(User, 0, request);
				} catch (Exception e) {

				}
			} else {
				token.clear();
			}
			//return "redirect:/index.do";
			return "/main/sysIndex";
		} catch (AuthenticationException e) {
			// redirectAttributes.addFlashAttribute("message","用户名或密码错误");
			ret.setResultCode(ObjResultCode.USER_LOGIN_USERNAME_PASSWORD_ERROR);
			model.addAttribute("ret", ret);
			return "redirect:/login.do";
		}
	}

	/**
	 * 首页
	 * 
	 * @return
	 */
	@RequestMapping(value = "/index.do", method = RequestMethod.GET)
	public String index(RedirectAttributes redirectAttributes) {

		Sys_User sysUser = (Sys_User) SecurityUtils.getSubject().getSession()
				.getAttribute(Constant_Cookie.CURRENT_USER_SESSION);
		if (sysUser == null) {
			redirectAttributes.addFlashAttribute("message", "登陆过期，请重新登陆");
			return "redirect:/login.do";
		}
		return "/main/sysIndex";
	}

	/**
	 * 欢迎页
	 * 
	 * @return
	 */
	@RequestMapping(value = "/welcome.do", method = RequestMethod.GET)
	public String welcome() {
		//return "/main/welcome";
		Sys_User sysUser = (Sys_User) SecurityUtils.getSubject().getSession().getAttribute(Constant_Cookie.CURRENT_USER_SESSION);
		if (sysUser == null) {
			return "redirect:/login.do";
		}
//		if(sysUser.getIsadmin()==1){
//			return "redirect:/info.do";
//		}
		return "/web/fullcalendar/index";
		//return "redirect:/info.do";
	}

	/**
	 * 注销
	 * 
	 * @param redirectAttributes
	 * @return
	 */
	@RequestMapping(value = "/logout.do", method = RequestMethod.GET)
	public String logout(RedirectAttributes redirectAttributes, Model model) {
		// 使用权限管理工具进行用户的退出，跳出登录，给出提示信息
		SecurityUtils.getSubject().logout();
		// redirectAttributes.addFlashAttribute("message", "您已安全退出");
		ObjResultException<String> ret = new ObjResultException<String>();
		ret.setResultCode(ObjResultCode.USER_SAFETY_EXIT_LOGIN);
		model.addAttribute("ret", ret);
		return "/login";
	}

	/**
	 * 403错误
	 * 
	 * @return
	 */
	@RequestMapping("/403")
	public String unauthorizedRole() {
		return "/403";
	}

	/**
	 * 获取验证码图片和文本(验证码文本会保存在HttpSession中)
	 */
	@RequestMapping("/getVerifyCodeImage.do")
	public void getVerifyCodeImage(HttpServletRequest request, HttpServletResponse response) throws IOException {
		// 设置页面不缓存
		response.setHeader("Pragma", "no-cache");
		response.setHeader("Cache-Control", "no-cache");
		response.setDateHeader("Expires", 0);
		String verifyCode = VerifyCodeUtil.generateTextCode(VerifyCodeUtil.TYPE_NUM_ONLY, 4, null);
		// 将验证码放到HttpSession里面
		request.getSession().setAttribute("verifyCode", verifyCode);
		System.out.println("本次生成的验证码为[" + verifyCode + "],已存放到HttpSession中");
		// 设置输出的内容的类型为JPEG图像
		response.setContentType("image/jpeg");
		BufferedImage bufferedImage = VerifyCodeUtil.generateImageCode(verifyCode, 90, 30, 3, true, Color.WHITE,
				Color.BLACK, null);
		// 写给浏览器
		ImageIO.write(bufferedImage, "JPEG", response.getOutputStream());
	}

	/**
	 * 系统左侧菜单
	 * 
	 * @return
	 */
	@RequestMapping("/")
	public String rootindex() {
		return "redirect:/login.do";
		// return "/index";
	}
}
